package org.munoz.shared;

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// //////////////////////////////////////////////////////////////////////////////



import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;


/**
 * Framework By : John K. Estell
 * 
 * Modified By : Juan Pablo Munoz on Sep/Oct/Nov 2013
 */


public class Deck {
  private LinkedList<Card> deck = new LinkedList<Card>();

  /**
   * Creates an empty deck of cards.
   */
  public Deck() {
//    restoreDeck();    
  }
  
  /**
   * Copy constructor.
   * */
  public Deck(Deck d) {
    deck.addAll(d.getCards());
  }

  public List<Card> getCards() {
    return Collections.unmodifiableList(deck);
  }
  
  public ArrayList<Card> getOrderedCards(){
	  ArrayList<Card> orderedCards = new ArrayList<Card>();
	  int index = 0;
	  for(int i=0; i<Rank.VALUES.length; i++){
		  for(int j=0; j<deck.size(); j++){
			  if(deck.get(j).getRank().ordinal() == i){
				  Card card = new Card(deck.get(j).getSuit(), deck.get(j).getRank());
				  orderedCards.add(card);
			  }
		  }
	  }
	  return orderedCards; 
  }

  /**
   * get a copy of this deck.
   * */
  public Deck getDeckCopy() {
    Deck d = new Deck(this);
    return d;
  }
  /**
   * The number of cards left in the deck.
   * 
   * @return the number of cards left to be dealt from the deck.
   */
  public int getNumberOfCardsRemaining() {
    return deck.size();
  }

  /**
   * Deal one card from the deck.
   * 
   * @return a card from the deck, or the null reference if there are no cards left in the deck.
   */
  public Card dealCard() {
    if (getNumberOfCardsRemaining() != 0) {
      return deck.poll();
    } else {
      return null;
    }
  }


  /**
   * Shuffles the cards present in the deck.
   */
  public void shuffle(IntGenerator generator) {
    Utils.shuffle(deck, generator);
  }


  /**
   * Looks for an empty deck.
   * 
   * @return <code>true</code> if there are no cards left to be dealt from the deck.
   */
  public boolean isEmpty() {
    if (getNumberOfCardsRemaining() == 0) {
      return true;
    }
    return false;

  }


  /**
   * Restores the deck to "full deck" status.
   */
  public void restoreDeck() {
    deck.clear();
    for (Suit s : Suit.values()) {
      for (Rank r : Rank.values()) {
        deck.add(new Card(s, r));
      }
    }
  }

  public Card getDeck(int index) {
    return deck.get(index);
  }
  
  
  // Additions and Modifications by JPM
 
  public void removeCardDeck(int index){
	  deck.remove(index);
  }
  public void addOneCard(Card c){
	  deck.addFirst(c);
  }
  
  
  // Remove card of same rank and suit
  public void removeOneCard(Card c){
	  for(int i=deck.size()-1; i>=0; i--){
//		  if(deck.get(i).rankToString().compareTo(c.rankToString())==0 && deck.get(i).suitToString().compareTo(c.suitToString())==0){
		  if(deck.get(i).getRank() == c.getRank() && deck.get(i).getSuit() == c.getSuit()){
		  	  deck.remove(i);
			  break;
		  }
	  }
  }
  
  public void removeAllCardsOfRank(Rank r){ 
	  for(int i=deck.size()-1; i>=0; i--){
		  if(deck.get(i).getRank() == r){
		  	  deck.remove(i);
		  }
	  }
  }
}